package com.gzs.learn.payment.service.api.impl;


import com.gzs.learn.common.util.HttpUtil.Response;
import com.gzs.learn.payment.model.cfg.PaycfgChannel;
import com.gzs.learn.payment.model.cfg.TokenYinlian;
import com.gzs.learn.payment.model.unionpay.pay.UnionpayRequest;
import com.gzs.learn.payment.model.unionpay.refund.UnionpayRefund;
import com.gzs.learn.payment.model.unionpay.refund.UnionpayRefundResult;
import com.gzs.learn.payment.util.SignUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;

import java.util.List;

import static com.gzs.learn.common.util.HttpUtil.doPost;
import static com.gzs.learn.common.util.HttpUtil.obj2Pair;
import static com.gzs.learn.payment.model.unionpay.UnionpayConstant.*;
import static com.gzs.learn.payment.util.AssertUtil.*;
import static com.gzs.learn.payment.util.CommonsUtil.convertToken;
import static com.gzs.learn.payment.util.CommonsUtil.httpResultToObj;

@Slf4j
public abstract class BaseUnionpay {
    protected final static String DOMAIN = "https://gateway.95516.com";
    protected final static String QUERY = DOMAIN + "/gateway/api/queryTrans.do";
    protected static final String YINLIAN_TRANS = DOMAIN + "/gateway/api/appTransReq.do";
    protected static final String YINLIAN_REFUND = DOMAIN + "/gateway/api/backTransReq.do";

    public UnionpayRefundResult unionpayRefund(UnionpayRefund unionpayRefund, PaycfgChannel paycfgChannel) {
        checkBlankStr(unionpayRefund.getOrderId(), "orderId can not be blank");
        checkBlankStr(unionpayRefund.getTxnTime(), "txtTime can not be blank");
        checkBlankStr(unionpayRefund.getOrigQryId(), "origOryId can not be blank");
        checkNumberPositive(unionpayRefund.getTxnAmt(), "txtAmt can not be null or 0");
        checkBlankStr(unionpayRefund.getBackUrl(), "refund url can not be blank");

        // 校验paycfgPla参数
        TokenYinlian tokenYinlian = convertToken(paycfgChannel.getToken(), TokenYinlian.class);
        checkToken(tokenYinlian);

        buildRefundCommonParams(unionpayRefund, tokenYinlian);
        String sign = SignUtil.yinlianSign(unionpayRefund, tokenYinlian);
        unionpayRefund.setSignature(sign);
        List<NameValuePair> listParam = obj2Pair(unionpayRefund);
        Response<String> resp = doPost(YINLIAN_REFUND, listParam, String.class);
        checkObjNotNull(resp, "call yinlian refund failed");
        checkArg(resp.isSuccess(), "call yinlian refund fail,controller code:" + resp.getHttpCode());
        log.info("refund result {}", resp.getEntity());
        UnionpayRefundResult result = httpResultToObj(resp.getEntity(), UnionpayRefundResult.class);
        checkObjNotNull(result, "get refund  object error");
        if (!SignUtil.yinlianSignVerify(result, tokenYinlian)) {
            checkArg(false, "signature error");
        }
        return result;
    }

    /**
     *
     * @param refund
     * @param tokenYinlian
     */
    protected void buildRefundCommonParams(UnionpayRefund refund, TokenYinlian tokenYinlian) {
        // 写入固定的的参数
        refund.setVersion(VERSION);
        refund.setEncoding(ENCODING_UTF8);
        refund.setTxnType(TXNTYPE_TUIHUO);
        refund.setTxnSubType("00");
        refund.setBizType(BIZTYPE_WANGGUANG_ZHIFU);
        refund.setChannelType("08");
        refund.setAccessType("0");
        refund.setMerId(tokenYinlian.getMerId());
        refund.setCertId(tokenYinlian.getCertid());
        refund.setSignMethod("01");
    }

    protected void checkToken(TokenYinlian token) {
        checkObjNotNull(token, "token must not be null");
        checkBlankStr(token.getMerId(), "merid can not be blank");
        checkBlankStr(token.getCertid(), "cerid can not be null");
        checkBlankStr(token.getCertkey(), "certKey can not be blank");
        checkBlankStr(token.getVerkey(), "verkey can not be blank");
        checkBlankStr(token.getEnckey(), "enckey can not be blank");
    }

    /**
     * 支付请求公共参数
     *
     * @param request
     * @param tokenYinlian
     */
    protected void buildUnionpayRequest(UnionpayRequest request, TokenYinlian tokenYinlian) {
        request.setVersion(VERSION);
        request.setEncoding(ENCODING_UTF8);
        request.setTxnType(TXNTYPE_XIAOFEI);
        request.setTxnSubType(TXNTYPE_XIAOFEI);
        request.setBizType(BIZTYPE_WANGGUANG_ZHIFU);
        request.setChannelType("08");
        request.setAccessType("0");
        request.setCurrencyCode(CURRENCY_CODE_RMB);
        request.setMerId(tokenYinlian.getMerId());
        request.setCertId(tokenYinlian.getCertid());
        request.setSignMethod("01");
    }
}
